﻿using System;
using System.Collections;
using ufida.u9.ait.openapi.utils;
using UFIDA.U9.Base;
using UFIDA.U9.Base.Organization;
using UFIDA.U9.Base.UOM;
using UFIDA.U9.CBO.Enums;
using UFIDA.U9.CBO.MFG.BOM;
using UFIDA.U9.CBO.MFG.CostElement;
using UFIDA.U9.CBO.MFG.Enums;
using UFIDA.U9.CBO.SCM.Item;
using UFIDA.U9.CBO.SCM.ProjectTask;
using UFIDA.U9.FA.FA_AssetCardBE;
using UFIDA.U9.SM.DealerSO;
using UFIDA.U9.Sn;
using UFSoft.UBF.Business;

namespace ufida.u9.ait.openapi
{
    internal class BOMMasterBase
    {
        /// <summary>
        /// 审核BOM
        /// </summary>
        /// <param name="entity"></param>
        /// <returns></returns>
        public static BOMMaster ApproveDoc(BOMMaster entity)
        {
            BOMApproveBP bp = new BOMApproveBP();
            bp.BOMID = entity.Key;
            bp.Do();
            return entity;
        }
        /// <summary>
        /// 弃审BOM
        /// </summary>
        /// <param name="entity"></param>
        /// <returns></returns>
        public static BOMMaster UnApproveDoc(BOMMaster entity)
        {
            BOMUnApproveBP bp = new BOMUnApproveBP();
            bp.BOMID = entity.Key;
            bp.Do();
            return entity;
        }
        /// <summary>
        /// 新增BOM
        /// </summary>
        /// <param name="dto"></param>
        /// <returns></returns>
        public static BOMMaster CreateDoc(BOMMasterAITDTOData dto)
        {
            BOMMaster entity;
            using (ISession session = Session.Open())
            {
                entity = CreateHead(dto);
                CreateLine(entity, dto);
                session.Commit();
            }
            return entity;
        }
        /// <summary>
        /// BOM更新
        /// </summary>
        /// <param name="entity"></param>
        /// <param name="dto"></param>
        /// <returns></returns>
        public static BOMMaster UpdateDoc(BOMMaster entity, BOMMasterAITDTOData dto)
        {
            using (ISession session = Session.Open())
            {
                UpdateHead(entity, dto);
                SyncLines(entity, dto);
                session.Commit();
            }
            return entity;
        }

        /// <summary>
        /// 行同步更新,支持新增/修改/删除
        /// </summary>
        /// <param name="master">bom头</param>
        /// <param name="dto">传入DTO</param>
        private static void SyncLines(BOMMaster master, BOMMasterAITDTOData dto)
        {
            //缓存BOM
            Hashtable hashbom = new Hashtable();
            int seq = 0;
            foreach (var comp in master.BOMComponents)
            {
                if (string.IsNullOrEmpty(comp.PLMID)) throw new Exception("BOM实体行:PLMID为空");
                String lineKey=comp.PLMID;
                if (hashbom.ContainsKey(lineKey))
                    throw new Exception($"料号[{comp.ItemMaster.Code}],PLMID[{lineKey}]重复!");
                hashbom.Add(lineKey, comp);
                if (seq < comp.Sequence)
                {
                    //计算最大行号
                    seq = comp.Sequence;
                }
            }

            //比对BOM表体,进行 新增/修改/删除操作
            //通过料号做对比
            foreach (var compdto in dto.BOMComponents)
            {
                if (string.IsNullOrEmpty(compdto.PLMID)) throw new Exception("DTO传入PLMID为空");
                String lineKey = compdto.PLMID;
                if (hashbom.Contains(lineKey))
                {
                    //该子项在实体中存在
                    //修改行
                    BOMComponent comp = (BOMComponent)hashbom[lineKey];
                    UpdateLine(comp, compdto);
                    hashbom.Remove(lineKey);
                }
                else
                {
                    //该子项不在实体中
                    //新增行
                    BOMComponent comp = BOMComponent.Create(master);
                    UpdateLine(comp, compdto);
                    seq += 10;
                    comp.Sequence = seq;
                }
            }

            //原BOM多出部分
            //删除行
            foreach (var key in hashbom.Keys)
            {
                BOMComponent comp = (BOMComponent)hashbom[key];
                comp.Remove();
            }
        }
        /// <summary>
        /// 更新BOM头
        /// </summary>
        /// <param name="master"></param>
        /// <param name="dto"></param>
        private static void UpdateHead(BOMMaster master, BOMMasterAITDTOData dto)
        {
            //组织,料品,单位
            if (string.IsNullOrEmpty(dto.Org?.Code))
            {
                master.Org = Context.LoginOrg;
            }
            else
            {
                master.Org = EntityUtils.GetEntityByCode<Organization>(dto.Org.Code);
            }
            if (string.IsNullOrEmpty(dto.ItemMaster?.Code))
                throw new Exception("ItemMaster为空");
            ItemMaster item = EntityUtils.GetEntityByCode<ItemMaster>(dto.ItemMaster.Code);
            master.ItemMaster = item;
            master.ProductUOM = item.ManufactureUOM;
            master.ProductAssistantUOM = item.ManufactureUOM.BaseUOM;
            //生产目的
            if (dto.AlternateType > -1)
            {
                master.AlternateType= AlternateTypesEnum.GetFromValue(dto.AlternateType);
            }
            else
            {
                master.AlternateType = AlternateTypesEnum.GetFromValue(0);
            }
            master.OperationYield = 1;
            master.Lot = 1;
            master.EffectiveDate = DateTime.Parse(dto.EffectiveDate ?? DateTime.Now.ToString());
            master.DisableDate = DateTime.Parse(dto.DisableDate ?? DateTime.MaxValue.ToString());
            master.BOMVersionCode = dto.BOMVersionCode;
            master.Project = EntityUtils.GetEntityByCode<Project>(dto.Project);
            master.IsPrimaryLot = true; //主批量
            master.IsCostRoll = true; //成本卷积默认
            master.Explain = dto.Explain;//备注
            //扩展字段处理
            if (dto.DescFlexField != null)
            {
                master.DescFlexField = new UFIDA.U9.Base.FlexField.DescFlexField.DescFlexSegments();
                DTOUtils.DTOPropCopy(dto.DescFlexField, master.DescFlexField);
            }
        }
        /// <summary>
        /// 更新行数据
        /// </summary>
        /// <param name="comp"></param>
        /// <param name="linedto"></param>
        private static void UpdateLine(BOMComponent comp, BOMComponentAITDTOData linedto)
        {
            if (string.IsNullOrEmpty(linedto.PLMID)) throw new Exception("传入PLMID为空");
            comp.PLMID = linedto.PLMID;
            comp.UsageQtyType = UsageQuantityTypeEnum.GetFromValue(linedto.UsageQtyType);
            comp.UsageQty = linedto.UsageQty;
            comp.TimeUOM = EntityUtils.GetEntityByCode<UOM>("Day");
            ItemMaster item = EntityUtils.GetEntityByCode<ItemMaster>(linedto.ItemMaster?.Code);
            comp.SupplyWareHouse = item.InventoryInfo.Warehouse;
            //comp.Sequence = linedto.Sequence == 0 ? i * 10 : linedto.Sequence;
            comp.Priority = linedto.Priority;
            comp.ParentQty = linedto.ParentQty;
            comp.OperationNum = linedto.OperationNum;
            comp.MinSelectedQty = linedto.MinSelectedQty;
            comp.MaxSelectedQty = linedto.MaxSelectedQty;
            comp.IUTOIAURate = 1;
            comp.ItemMaster = item;
            comp.IssueUOM = item.MaterialOutUOM;
            comp.IssueAssistantUOM = item.MaterialOutUOM.BaseUOM;
            if (string.IsNullOrEmpty(linedto.IssueOrg?.Code))
            {
                comp.IssueOrg = Context.LoginOrg;
            }
            else
            {
                comp.IssueOrg = EntityUtils.GetEntityByCode<Organization>(linedto.IssueOrg.Code);
            }
            comp.IsIssueOrgFixed = linedto.IsIssueOrgFixed;
            comp.IsEffective = true;//生效
            comp.IsDefault = true;
            comp.IsCharge = true;
            comp.IsCalcPrice = true;
            comp.EffectiveDate = DateTime.Parse(linedto.EffectiveDate ?? DateTime.Now.ToString());//生效日期
            comp.DisableDate = DateTime.Parse(linedto.DisableDate ?? DateTime.MaxValue.ToString());//失效日期
            comp.CostElement = CostElement.Finder.FindByID(item.MfgInfo.CostElement);
            comp.ConsignProcessItemSrc = ConsignProcessItemSrcEnum.GetFromValue(linedto.ConsignProcessItemSrc);
            comp.CompProject = EntityUtils.GetEntityByCode<Project>(linedto.Project);

            comp.SetChkAtWorkingStart = linedto.SetChkAtWorkingStart;//订单开工
            comp.SetChkAtComplete = linedto.SetChkAtComplete;//订单完工
            comp.SetChkAtOptStart=linedto.SetChkAtOptStart;//工序开工
            comp.SetChkAtOptComplete = linedto.SetChkAtOptComplete;//工序完工

            comp.IsSpecialUseItem = linedto.IsSpecialUseItem;//专项控制
            comp.IsOverIssue = linedto.IsOverIssue;//允许超额发料
            if (linedto.MaterialType >= 0)
            {
                comp.MaterialType = IsSueOverTypeEnum.GetFromValue(linedto.MaterialType);//超额类型
            }
            comp.StandardMaterialScale=linedto.StandardMaterialScale;//标准超额比例
            comp.IsPhantomPart=linedto.IsPhantomPart;//虚拟
            comp.ScrapType = ScrapTypeEnum.GetFromValue(linedto.ScrapType);//损耗类型
            comp.FixedScrap=linedto.FixedScrap;//固定损耗
            comp.Scrap=linedto.Scrap;//变动损耗
            comp.PlanPercent=linedto.PlanPercent;//计划百分比
            comp.Remark=linedto.Remark;//备注
            //扩展字段处理
            if (linedto.DescFlexField != null)
            {
                comp.DescFlexField = new UFIDA.U9.Base.FlexField.DescFlexField.DescFlexSegments();
                DTOUtils.DTOPropCopy(linedto.DescFlexField, comp.DescFlexField);
            }
        }
        /// <summary>
        /// 创建行
        /// </summary>
        /// <param name="master"></param>
        /// <param name="dto"></param>
        private static void CreateLine(BOMMaster master, BOMMasterAITDTOData dto)
        {
            int i = 0;
            foreach (var linedto in dto.BOMComponents)
            {
                i++;
                BOMComponent comp = BOMComponent.Create(master);
                UpdateLine(comp, linedto);
                comp.Sequence = linedto.Sequence == 0 ? i * 10 : linedto.Sequence;//子件项次
            }
        }
        /// <summary>
        /// 创建BOM头
        /// </summary>
        /// <param name="dto"></param>
        /// <returns></returns>
        private static BOMMaster CreateHead(BOMMasterAITDTOData dto)
        {
            BOMMaster master = BOMMaster.Create();
            UpdateHead(master, dto);
            return master;
        }
    }
}
